package fresher.server;


import fresher.model.ModelManager;
import fresher.profilerLogUtility.WriteProfilerLog;
import fresher.utility.BlockingQueueConnectionPool;
import fresher.utility.ConnectionPool;
import fresher.utility.TemplateManager;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.thread.QueuedThreadPool;

/**
 * Web server
 */
public class WebServer {

    public static void main(String args[]) throws Exception {
        //Crate new server instance
        Server server = new Server();

        //Thread pool config
        /*
         *  A pool of threads.
         *  Avoids the expense of thread creation by pooling threads
         *  after their run methods exit for reuse.
         *  If an idle thread is available a job is directly dispatched,
         *  otherwise the job is queued.
         *  After queuing a job, if the total number of threads is less than the maximum pool size,
         *  a new thread is spawned. 
         */
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMinThreads(100);
        threadPool.setMaxThreads(500);
        server.setThreadPool(threadPool);

        //Connector config
        /*
         *  This connector uses efficient NIO buffers with a non blocking threading model.
         *  Direct NIO buffers are used and threads are only allocated to connections
         *  with requests.
         *  Synchronization is used to simulate blocking for the servlet API,
         *  and any unflushed content at the end of request handling is written asynchronously.
         *  This connector is best used when there are a many connections that have idle periods. 
         */
        SelectChannelConnector connector = new SelectChannelConnector();
        
        /*
         * The TCP/IP port on which the connector listens for connections
         * is set using the the XML Property element
         * which looks up the jetty.port (or jetty.tls.port) property,
         * and if not found defaults to 8080 (or 8443 for TLS).
         */
        connector.setPort(8080);
        
        /*
         * Idle time: The time in milliseconds that a connection can be idle
         * before the connector takes action to close the connection.
         * 
         * Set the maximum Idle time for a connection,
         * which roughly translates to the Socket.setSoTimeout(int) call,
         * although with NIO implementations other mechanisms may be used to implement the timeout.
         * The max idle time is applied: 
         *      - When waiting for a new request to be received on a connection
         *      - When reading the headers and content of a request
         *      - When writing the headers and content of a response
         * 
         */
        connector.setMaxIdleTime(30000);
        
        /*
         * The port to use when redirecting a request
         * if a data constraint of confidential is required.
         */
        connector.setConfidentialPort(8443);
        
        /*
         *  disables statistics collection
         * (Detailed statistics on connection duration and number of requests are only collated when a connection is closed.)
         * on connections.
         */
        connector.setStatsOn(false);
        
        /*
         * Set the number of connections, which if exceeded places this manager in low resources state.
         * This is not an exact measure as the connection count is averaged over the select sets.
         */
        connector.setLowResourcesConnections(20000);
        
        /*
         * Set the period in ms that a connection is allowed to be idle
         * when this there are more than getLowResourcesConnections() connections.
         * This allows the server to rapidly close idle connections
         * in order to gracefully handle high load situations
         */
        connector.setLowResourcesMaxIdleTime(5000);
        
        server.setConnectors(new Connector[]{connector});

        //Resource handler to server for static file
        ResourceHandler resourceHandler = new ResourceHandler();
        resourceHandler.setDirectoriesListed(true);
        resourceHandler.setWelcomeFiles(new String[]{"index.html"});
        resourceHandler.setResourceBase(".");

        //Prepare connection
        BlockingQueueConnectionPool.getBQConnectionPool();
        
        //Prepare connection
        ConnectionPool.getConnectionPool();
        
        //Prepare write log 
        WriteProfilerLog.getWriteProfilerLog();
        
        //Prepare model
        ModelManager.getModelManager();
        
        //Create template manager
        TemplateManager.getInstance();
        
        //Create a handlerlist
        HandlerList handlers = new HandlerList();

        //Add servlet handler
        ServletHandler handler = new ServletHandler();

        // Bill detail handler
        handler.addServletWithMapping(
                "fresher.servletcontroller.BillDetailServletController", "/bill-detail/*");

        // Table management controller
        handler.addServletWithMapping(
                "fresher.servletcontroller.TableManagementServletController", "/table/*");
        
        handler.addServletWithMapping(
                "fresher.servletcontroller.IndexServletController", "/admin");
        
        handler.addServletWithMapping(
                "fresher.servletcontroller.BillServletController", "/bill");

        
        handler.addServletWithMapping(
                "fresher.servletcontroller.TotalRenderServletController", "/total");
        
            handler.addServletWithMapping(
                "fresher.servletcontroller.TotalServletController", "/total_result");
            
        handlers.setHandlers(new Handler[]{resourceHandler, handler});

        server.setHandler(handlers);

        server.setStopAtShutdown(true);
        server.setSendServerVersion(true);

              
        
        server.start();
        server.join();
    }
}
